package com.laoxu.test.sqlitedemo.config;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * JAVA8时间日期工具类
 *
 * @author zhangbin
 * @date 2018/12/26
 */
public class Java8DateUtils {

    public static final String DATE_PATTERN = "yyyy-MM-dd";

    public static final String TIME_PATTERN = "HH:mm:ss";

    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 毫秒时间戳转LocalDateTime
     *
     * @param timeMillis 毫秒时间戳
     * @return LocalDateTimeO
     */
    public static LocalDateTime toLocalDateTime(long timeMillis) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeMillis), ZoneId.systemDefault());
    }

    /**
     * 毫秒时间戳转LocalDate
     *
     * @param timeMillis 毫秒时间戳
     * @return LocalDate
     */
    public static LocalDate toLocalDate(long timeMillis) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeMillis), ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * java8 LocalDate 转化成旧的日期
     *
     * @param localDate
     * @return
     */
    public static Date localDate2UtilDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * java8 LocalDateTime 转换成旧的日期
     *
     * @param localDateTime
     * @return
     */
    public static Date localDateTime2UtilDate(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 传统日期转换成LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * 传统日期转换成LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate date2LocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDate();
    }

    /**
     * LocalDateTime 对应的毫秒值
     *
     * @param localDateTime
     * @return
     */
    public static long parseLocalDateTime2TimeMillis(LocalDateTime localDateTime) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        return instant.toEpochMilli();
    }

    /**
     * LocalDate 对应的毫秒值
     *
     * @param localDate
     * @return
     */
    public static long parseLocalDate2TimeMillis(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.of(0, 0, 0));
        Instant instant = localDateTime.atZone(zone).toInstant();
        return instant.toEpochMilli();
    }

    /**
     * LocalDateTime 对应的字符串
     *
     * @param localDateTime
     * @param pattern       格式 例如 yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String getDateStrWithFormate(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern(pattern);
        return dtf2.format(localDateTime);
    }

    /**
     * localDate 对应的字符串
     *
     * @param localDate
     * @param pattern   格式 例如 yyyy-MM-dd
     * @return
     */
    public static String getDateStrWithFormate(LocalDate localDate, String pattern) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern(pattern);
        return dtf2.format(localDate);
    }

    /**
     * localTime 对应的字符串
     *
     * @param localTime 18:23:32
     * @param pattern   格式 例如 HH:mm:ss
     * @return 18:23:32
     */
    public static String getTimeStrWithFormate(LocalTime localTime, String pattern) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern(pattern);
        return dtf2.format(localTime);
    }

    /**
     * 字符串到日期
     *
     * @param strDate
     * @param pattern
     * @return
     */
    public static LocalDate convertDateStrToLocalDate(String strDate, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(strDate, dateTimeFormatter);
    }

    /**
     * 字符串到时间
     *
     * @param strTime strTime
     * @param pattern pattern
     * @return LocalTime
     */
    public static LocalTime convertDateStrToLocalTime(String strTime, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalTime.parse(strTime, dateTimeFormatter);
    }

    /**
     * 字符串到日期时间
     *
     * @param strDate
     * @param pattern
     * @return
     */
    public static LocalDateTime convertDateStrToLocalDateTime(String strDate, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(strDate, dateTimeFormatter);
    }

    /**
     * 字符串到毫秒值
     *
     * @param strDate
     * @param pattern
     * @return
     */
    public static long convertDateToLong(String strDate, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        LocalDate date = LocalDate.parse(strDate, dateTimeFormatter);
        return parseLocalDate2TimeMillis(date);
    }

    /**
     * 毫秒值到对应的字符串
     *
     * @param timestamp
     * @param pattern
     * @return
     */
    public static String convertLongToDateStr(long timestamp, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        LocalDateTime localDateTime = toLocalDateTime(timestamp);
        return localDateTime.format(formatter);
    }

    public static Instant toInstant(LocalDate localDate) {
        LocalDateTime localDateTime = LocalDateTime.of(localDate, LocalTime.MIN);
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    public static Instant toInstant(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    public static LocalDateTime toLocalDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }


    public static LocalDateTime toZone(LocalDateTime time, ZoneId fromZone, ZoneId toZone) {
        final ZonedDateTime zonedDateTime = time.atZone(fromZone);
        final ZonedDateTime converted = zonedDateTime.withZoneSameInstant(toZone);
        return converted.toLocalDateTime();
    }

    public static LocalDateTime defaultToZone(LocalDateTime time, ZoneId toZone) {
        return toZone(time, ZoneId.systemDefault(), toZone);
    }

    public static LocalDateTime zoneToDefaultZone(LocalDateTime time, ZoneId fromZone) {
        return toZone(time, fromZone, ZoneId.systemDefault());
    }

    public static LocalDateTime toUtc(LocalDateTime time, ZoneId fromZone) {
        return toZone(time, fromZone, ZoneOffset.UTC);
    }

    public static LocalDateTime toUtc(LocalDateTime time) {
        return toUtc(time, ZoneId.systemDefault());
    }

    /**
     * 将一个时区的时间转换为另一个时区的时间
     *
     * @param dateTime fromZone datetime
     * @param fromZone fromZone
     * @param toZone   toZone
     * @return 转换后对应时区的时间
     */
    public static LocalDateTime convertTimeZone(LocalDateTime dateTime, ZoneId fromZone, ZoneId toZone) {
        return dateTime.atZone(fromZone).withZoneSameInstant(toZone).toLocalDateTime();
    }

    /**
     * 将一个时区的时间戳转换为另一个时区的时间戳
     *
     * @param dateTime fromZone datetime
     * @param fromZon  fromZone
     * @param toZone   toZone
     * @return 转换后对应时区的时间戳
     */
    public static long convertTimeZone(long dateTime, ZoneId fromZon, ZoneId toZone) {
        LocalDateTime fromTime = toLocalDateTime(dateTime);
        LocalDateTime toTime = convertTimeZone(fromTime, fromZon, toZone);
        return parseLocalDateTime2TimeMillis(toTime);
    }

}
